#coding=utf-8

import time
import datetime
import random
import re
from Cookie import SimpleCookie
from operator import itemgetter
from django.utils import simplejson
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import users
from google.appengine.ext import db

class Statement(db.Model):
  id = db.StringProperty(required=True)
  fee = db.FloatProperty(required=True)
  currency = db.StringProperty(required=True)
  desc = db.StringProperty()
  tag = db.ListProperty(str)
  time = db.DateTimeProperty(auto_now_add=True)

class CashUserProfile(db.Model):
  id = db.StringProperty(required=True)
  guid = db.StringProperty(required=True)
  dfCurrency = db.StringProperty(required=True)


class DelStatement(webapp.RequestHandler):
  def get(self):
	user = users.get_current_user()
	if not user:
		greeting = ("<a href=\"/\">back to home</a>.")
		self.response.out.write("<html><title>afiie</title><body>%s</body></html>" % greeting)
		return

	# cookie
	c = SimpleCookie()
	c.load(self.request.cookies)
	# bid
	if not c.has_key("id"):
		greeting = ("<a href=\"/\">please login</a>.")
		self.response.out.write("<html><title>afiie</title><body>%s</body></html>" % greeting)
		return

	self.request.charset='utf-8'
	id = self.request.cookies["id"]
	del_time_t = self.request.get('t')
	ok = self.request.get('ok')
	if ok != "1":
		greeting = ("Do you really want to DELETE? <font size=+3><a href=\"/r?%s\">NO</a></font> <font size=-2><a href=\"/d?t=%s&ok=1\">YES</a></font>" % (del_time_t ,del_time_t) )
		self.response.out.write("<html><title>afiie</title><body>%s</body></html>" % greeting)
		return

	del_dattime_d = datetime.datetime.fromtimestamp( float(del_time_t) )
	del_dattime_t = datetime.datetime.fromtimestamp( float(del_time_t) + 1 )

	q = db.GqlQuery("SELECT * FROM Statement WHERE id = :1 AND time >= :2 AND time < :3", id, del_dattime_d, del_dattime_t )
	results = q.fetch(1)
	for result in results:
		result.delete()
	
	self.redirect("/r?"+del_time_t)


class WriteStatement(webapp.RequestHandler):
  def post(self):
	user = users.get_current_user()
	if not user:
		greeting = ("<a href=\"/\">back to home</a>.")
		self.response.out.write("<html><title>afiie</title><body>%s</body></html>" % greeting)
		return
	# get
	self.request.charset='utf-8'
	dfCurrency = self.request.get('dfCurrency')	  
	# cookie
	c = SimpleCookie()
	c.load(self.request.cookies)
	# bid
	if not c.has_key("id"):
		greeting = ("<a href=\"/conf\">please tell us your preference</a>.")
		self.response.out.write("<html><title>afiie</title><body>%s</body></html>" % greeting)
		return

	# get input
	self.request.charset='utf-8'
	id = self.request.cookies["id"]
	fee = self.request.get('fee')

	# valid input
	if fee == "":
		greeting = ("fee is needed <a href=\"javascript:history.go(-1);\">back to previous</a>.")
		self.response.out.write("<html><title>afiie</title><body>%s</body></html>" % greeting)
		return
	try:
		float_valid = float(fee)
	except:
		greeting = ("fee must be int or float <a href=\"javascript:history.go(-1);\">back to previous</a>.")
		self.response.out.write("<html><title>afiie</title><body>%s</body></html>" % greeting)
		return

	tag = self.request.get('tag')
	desc = self.request.get('desc')
	currency = self.request.get('currency')
	if currency == "":
		currency = self.request.cookies["dfCurrency"]

	# db access
	stmt = Statement(
			id = str(id),
			fee = float(fee),
			currency = currency,
			desc = desc,
			tag = tag.split(',')
			)
	stmt.put()
	
	# output
	monthSum = 0
	firstDayOfMonth = datetime.datetime.fromtimestamp(time.mktime(time.strptime(datetime.datetime.today().strftime("%Y-%m-01"), "%Y-%m-%d")))
	spendList = db.GqlQuery("SELECT * FROM Statement WHERE id = :1 AND time >= :2", id, firstDayOfMonth )
	for spend in spendList:
		monthSum += spend.fee

	self.response.out.write("""<html><title>afiie: save done</title><body>
<div>save done</div>
<div>monthly spending is reach: <span  style="margin: 5pt; font-size: 20px;color: #82983e;" >"""+str(monthSum)+"""</span></div>
<div><a href="/">back to home</a></div>
</body></html>""")


class ReadStatement(webapp.RequestHandler):
  def get(self):
	user = users.get_current_user()
	if not user:
		greeting = ("<a href=\"/\">back to home</a>.")
		self.response.out.write("<html><title>afiie</title><body>%s</body></html>" % greeting)
		return

	# cookie
	c = SimpleCookie()
	c.load(self.request.cookies)
	# bid
	if not c.has_key("id"):
		greeting = ("<a href=\"/\">please login</a>.")
		self.response.out.write("<html><title>afiie</title><body>%s</body></html>" % greeting)
		return

	self.request.charset='utf-8'
	id = self.request.cookies["id"]
	month = self.request.get('m')

	# db
	monthSum = 0
	if month == "":
		firstDayOfMonth_t = time.mktime(time.strptime(datetime.datetime.today().strftime("%Y-%m-01"), "%Y-%m-%d"))
		next_month_struct_time = time.localtime(firstDayOfMonth_t + 82400*32)
		last_month_struct_time = time.localtime(firstDayOfMonth_t - 82400)
		month = time.strftime("%Y-%m", time.localtime(firstDayOfMonth_t))
		begin = datetime.datetime.fromtimestamp(firstDayOfMonth_t)
		# access
		spendList = db.GqlQuery("SELECT * FROM Statement WHERE id = :1 AND time >= :2", id, begin )
	else:
		month_struct_time = time.strptime(month ,"%Y-%m")
		firstDayOfMonth_t = time.mktime(time.strptime(time.strftime("%Y-%m-01", month_struct_time) ,"%Y-%m-%d"))
		next_month_struct_time = time.localtime(firstDayOfMonth_t + 86400*32)
		last_month_struct_time = time.localtime(firstDayOfMonth_t - 86400)
		firstDayOfNextMonth_t = time.mktime(time.strptime(time.strftime("%Y-%m-01", next_month_struct_time) ,"%Y-%m-%d"))
		begin = datetime.datetime.fromtimestamp(firstDayOfMonth_t)
		end = datetime.datetime.fromtimestamp(firstDayOfNextMonth_t)
		# access
		query = db.Query(Statement)
		query.filter('id =', id)
		query.filter('time >=', begin).filter('time <', end)
		spendList = query.fetch(1000)

	# output
	n = time.strftime("%Y-%m", next_month_struct_time)
	l = time.strftime("%Y-%m", last_month_struct_time)
	pagination = ("<a href=\"/r?m=%s\">last</a> %s <a href=\"/r?m=%s\">next</a>" % (l ,month ,n ))
	self.response.out.write("""<html><title>afiie: expense report</title><meta http-equiv="content-type" content="text/html; charset=UTF-8"><style type="text/css"> .right {text-align:right;} td {padding:2px 10px;} </style>
<body>
<div>
<div>"""+pagination+"""</div>
<table border=0>""")
	for s in spendList:
		monthSum += s.fee
		time_t = time.mktime(time.strptime(s.time.strftime("%Y-%m-%d %H:%M:%S"), "%Y-%m-%d %H:%M:%S"))
		#time_t = s.time.strftime("%Y-%m-%d %H:%M:%S %f")
		self.response.out.write("""<tr><td><a href='/d?t=%s'>D</a><td class=right>%s<td>%s<td>%s<td>%s""" % (str(time_t) ,str(s.fee) ,s.currency ,s.time.strftime("%m/%d") ,s.desc +' ' ))
		for tag in s.tag:
			self.response.out.write(tag+ " " )


	self.response.out.write("""</table><div>summary: <span  style="margin: 5pt; font-size: 20px;color: #82983e;">"""+str(monthSum)+"""</span></div>

<div>"""+pagination+"""</div>
<div><a href="/">back to home</a></div>
</body></html>""")
				

class Profiling(webapp.RequestHandler):
  def get(self):
	user = users.get_current_user()
	if not user:
		greeting = ("<a href=\"/\">back to home</a>.")
		self.response.out.write("<html><title>afiie</title><body>%s</body></html>" % greeting)
		return
	# get
	self.request.charset='utf-8'
	dfCurrency = self.request.get('dfCurrency')
	if dfCurrency == "":
		self.response.out.write("""<html><title>afiie</title><style type="text/css">form div {clear:left; margin:5px 0 0;} .in {display:block; float:left; width:60px; margin:0 0 5px; padding:3px 5px; text-align:right; border: 1px solid #FFFFFF;background: #FFFFFF;font-family: tahoma, helvetica, sans-serif;font-style: normal;font-size: 14px;color: #454743;} .la {font-family: tahoma, helvetica, sans-serif;font-style: bold;font-size: 13px;color: #82983e;}</style><body>
<div>
<form action="/conf" method="get">
<div><label class="in">currency</label><input class="la" type=text name=dfCurrency> ex. USD, RMB, TWD</div>
<div><label class="in"></label><input class="la" type="submit" value="Train"></div>
</form>
<div><a href="/">back to home</a></div>
</div>
</body></html>""")
		return
	
	# db
	profileList = db.GqlQuery("SELECT * FROM CashUserProfile WHERE guid = :1", user.email())
	if profileList.count() > 1:
		self.response.out.write( "system error: dup guid %s" % user.email())
		return

	if profileList.count() == 0:
		# insert
		id = random.randint(1,99999999)
		idList = db.GqlQuery("SELECT * FROM CashUserProfile WHERE id = :1", id)
		if idList.count() == 0:
			p = CashUserProfile(	id = str(id), 
						guid = user.email(),
						dfCurrency = dfCurrency
						)
			p.put()
		else:
			self.response.out.write( "system error: dup id %s" % id)
			return
	else:
		#update
		for profile in profileList:
			id = profile.id
			profile.dfCurrency = dfCurrency
			profile.put()

	# cookie
	c = SimpleCookie()
	#c.load(self.request.cookies)
	# save to cookie
	c["id"] = str(id)
	c["id"]["expires"]= str(time.time() + 60*60*24*365)
	c["id"]["path"]="/"
	header_value = c["id"].output(header='').lstrip()
	self.response.headers._headers.append(('Set-Cookie', header_value))
	c["dfCurrency"] = dfCurrency
	c["dfCurrency"]["expires"]= str(time.time() + 60*60*24*365)
	c["dfCurrency"]["path"]="/"
	header_value = c["dfCurrency"].output(header='').lstrip()
	self.response.headers._headers.append(('Set-Cookie', header_value))

	self.redirect("/")
	  

class About(webapp.RequestHandler):
  def get(self):
	self.response.out.write("""<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>afiie: about</title><style type="text/css"> div {width: 600px; margin:5px 0 0; font-family: tahoma, helvetica, sans-serif;font-style: normal;font-size: 20px;color: #454743;} </style>
</head><body><div>
<div>5expens.appspot.com is expense recorder. Personal finance management is important, and writing down daily expense is the first step to start the management. 5expens.appspot.com wants to help daily routine task to be easy.</div> 
<div><em>fee</em> is the only field you must provide.</div> 
<div><em>tag</em> helps to classify your expense . such as expense type (dine, traffic, lodging, entertainment...etc), or use as payment type (cash, credit, mortgage). <em>tag</em> supports multiple values and must be seperated by comma(',') charater.</div>
<div><em>desc</em> is for recording more detail.</div>
<div><a href="/r">expense report</a> lets you browse your expense history monthly and export your data.</div>
<div>In <a href="/conf">preference</a>, you can set personal config such as default currency type, such as USD, YEN, EUR, RMB ... etc.</div>
<div><a href="/">back to home</a></div>
</div></body></html>""")


# json response for ajax
class TagList(webapp.RequestHandler):
  def get(self):
	user = users.get_current_user()
	if not user:
		return

	# cookie
	c = SimpleCookie()
	c.load(self.request.cookies)
	# bid
	if not c.has_key("id"):
		return

	self.request.charset='utf-8'
	id = self.request.cookies["id"]
	firstDayOfMonth_t = time.mktime(time.strptime(datetime.datetime.today().strftime("%Y-%m-01"), "%Y-%m-%d"))
	begin = datetime.datetime.fromtimestamp(firstDayOfMonth_t  - 82400*30)

	taglist = {}
	# access
	query = db.Query(Statement)
	query.filter('id =', id)
	query.filter('time >=', begin)
	spendList = query.fetch(1000)
	for s in spendList:
		for tag in s.tag:
			if tag in taglist:
				taglist[tag] += 1
			else:
				taglist[tag] = 1
	
	jEncode = simplejson.JSONEncoder()
	self.response.out.write(jEncode.encode(taglist))


class MainHandler(webapp.RequestHandler):
  def get(self):
	user = users.get_current_user()
	if not user:
		greeting = ("<a href=\"%s\">Sign in or register</a>." % users.create_login_url("/"))
		self.response.out.write("<html><title>afiie</title><body><div>%s</div> <div><a href=\"/about\">about</a></div></body></html>" % greeting)

		return

	# cookie
	c = SimpleCookie()
	c.load(self.request.cookies)
	# bid
	if not (c.has_key("id") and c.has_key("dfCurrency")):
		greeting = ("<a href=\"/conf\">please tell us your preference</a>.")
		self.response.out.write("<html><title>afiie</title><body><div>%s</div> <div><a href=\"/about\">about</a></div></body></html>" % greeting)
		return
	else:
		id = self.request.cookies["id"]
		dfCurrency = self.request.cookies["dfCurrency"]

    	self.response.out.write("""<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>afiie: input</title><style type="text/css">form div {clear:left; margin:5px 0 0;} .in {display:block; float:left; width:60px; margin:0 0 5px; padding:3px 5px; text-align:right; border: 1px solid #FFFFFF;background: #FFFFFF;font-family: tahoma, helvetica, sans-serif;font-style: normal;font-size: 14px;color: #454743;} .la {font-family: tahoma, helvetica, sans-serif;font-style: bold;font-size: 13px;color: #82983e;} #tag {display:none;}</style>
</head><body>
<div>恭喜發財 """+user.nickname()+"""</div>
<div>
<form action="/w" method="post">
<div><label class="in">fee*</label><input class="la" type=text name=fee></div>
<div><label class="in"></label><input class="la" type=submit></div>
<div><label class="in">tag</label><input class="la" id="tagtxt" type=text name=tag> <a href="#" class="showtag">></a> <span id="tag"></span> seperated by comma(',')</div>
<div><label class="in">desc</label><input class="la" type=text name=desc></div>
<div><label class="in">currency*</label><input class="la" type=text name=currency value="""+str(dfCurrency)+"""></div>
</form>
</div>
<div><a href="/r">expense report</a></div>
<div><a href="/conf">preference</a></div>
<div><a href="/about">about</a></div>
</body>
<script type="text/javascript" src="/js/jquery.js"></script>
  <script>
  $(document).ready(function(){
    $.getJSON("/taglist",
        function(data){
          $.each(data, function(tag,freq){
            //alert(tag+','+freq);
	    $("#tag").append("<a href='#' class='tag'>"+tag+"</a> ");
          });
        });
  });
  $("a.showtag").live("click",function(){$("#tag").toggle(); return false;});
  $("a.tag").live("click",function(){document.getElementById("tagtxt").value = $(this).text(); return false;});
  </script>
</html>""")


def main():
  application = webapp.WSGIApplication([('/', MainHandler),
	  				('/w',WriteStatement),
	  				('/r',ReadStatement),
	  				('/d',DelStatement),
	  				('/taglist',TagList),
	  				('/conf',Profiling),
	  				('/about',About)],
                                       debug=True)
  run_wsgi_app(application)


if __name__ == '__main__':
  main()
